var push = 'push',
  readyState = 'readyState',
  onreadystatechange = 'onreadystatechange',
  head = document.querySelector('head'),
  scripts = {},
  ids = {},
  delays = {}

function loadjs(paths, async, idOrDone, optDone) {
  if(async === undefined) {
    async = true
  }
  paths = paths[push] ? paths : [paths]

  var idOrDoneIsDone = idOrDone && idOrDone.call,
    done = idOrDoneIsDone ? idOrDone : optDone,
    id = idOrDoneIsDone ? paths.join('') : idOrDone,
    queue = paths.length

  function callback() {
    if (!--queue) {
      ids[id] = 1
      done && done()

      for (let keys in delays) {
        if (keys.split('|').every(key => ids[key])) {
          delays[keys].forEach(fn => fn())
          delays[keys] = []
        }
      }
    }
  }

  paths.forEach(function loading(path) {
    if (path === null) return callback()

    if (scripts[path]) {
      scripts[path] === 2 ? callback() : loading(path)
    } else {
      scripts[path] = 1
      create(path, callback, async)
    }
  })
}

function create(path, fn, async) {
  var el = document.createElement('script')
  el.onload = el[onreadystatechange] = function(e) {
    if (e.type === 'load' || /^(complete|loaded)$/.test(el[readyState])) {
      el.onload = el[onreadystatechange] = el.onerror = null
      scripts[path] = 2
      fn()
    }
  }
  el.onerror = function(e) {
    el.onload = el[onreadystatechange] = el.onerror = null
    throw new Error(`Script error for ${path}`)
  }
  el.async = async
  el.src = path
  head.insertBefore(el, head.lastChild)
}

function ready(deps, fn) {
  deps = deps[push] ? deps : [deps]

  deps.every(dep => ids[dep])
    ? fn()
    : !(function(key) {
        delays[key] = delays[key] || []
        delays[key][push](fn)
      })(deps.join('|'))
}

loadjs.ready = ready

export default loadjs
